package com.exploadingelephants.sprite;

import java.util.Date;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.view.View;

/**
 * Definition of a Sprite. Any visible object during game play should inherit
 * this class.
 */
abstract public class Sprite implements Comparable<Sprite> {
    /** Movement of an object */
    Movement movement;
    /** Width of an object */
    protected int width;
    /** Height of an object */
    protected int height;
    /** Bitmap used to represent this object */
    protected Bitmap bmp;
    /** Visibility */
    protected boolean visible;
    /** object id */
    protected long id;
    /** Date of creation */
    protected Date creationDate;
    /** Main PlaygroundView */
    protected View parentView;

    /**
     * @param context
     * @param id
     */
    public Sprite(View context, long id) {
	this.parentView = context;
	this.visible = true;
	this.creationDate = new Date();
	this.id = id;
    }

    /**
     * Every sprite object will be informed to update itself
     * 
     * @param ball
     */
    abstract protected void update();

    /** Every sprite should set its own image */
    abstract protected void setImage();

    /** Sets the initial sprite movement/position */
    abstract public void setDefaultMovement();

    /**
     * draws the sprite after updating the movement
     * 
     * @param canvas
     * @param ball
     */
    public void updateSprite(Canvas canvas) {
	update();
	canvas.drawBitmap(bmp, movement.getxPosition(),
		movement.getyPosition(), null);
    }

    /**
     * Checks is this sprite collides with another sprite
     */
    public boolean isColliding(Sprite other) {
	return this.isVisible() && other.isVisible() && isYColliding(other)
		&& isXColliding(other);
    }

    /**
     * Checks for a collision on y-axis with another sprite
     * 
     * @param other
     * @return
     */
    private boolean isYColliding(Sprite other) {
	return other.movement.getyPosition() <= movement.getyPosition()
		+ height
		&& other.movement.getyPosition() + other.height >= movement
			.getyPosition();
    }

    /**
     * Checks for a collision on y-axis with another sprite
     * 
     * @param other
     * @return
     */
    private boolean isXColliding(Sprite other) {
	return other.movement.getxPosition() <= movement.getxPosition() + width
		&& other.movement.getxPosition() + other.width >= movement
			.getxPosition();
    }

    /**
     * Defines what should happen when colliding with another sprite
     * 
     * @param sprite
     */
    public void collide(Sprite sprite) {
	this.die();
    }

    /**
     * An elephant just died
     */
    public void die() {
	this.visible = false;
    }

    /**
     * Visibility checker
     * 
     * @return
     */
    public boolean isVisible() {
	return this.visible;
    }

    /**
     * Default sorting of Sprites is by creation date
     */
    public int compareTo(Sprite other) {
	return this.creationDate.compareTo(other.creationDate);
    }

    @Override
    public String toString() {
	return this.getClass().getName() + ":" + this.id;
    }
}
